2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11 * Public License for more details.
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 #import "adiumPurpleBlist.h"
18 #import <AIUtilities/AIObjectAdditions.h>
19 #import <Adium/AIListContact.h>
21 static NSMutableDictionary *groupDict = nil;
22 static NSMutableDictionary *aliasDict = nil;
24 static void adiumPurpleBlistNewList(PurpleBuddyList *list)
29 static void adiumPurpleBlistNewNode(PurpleBlistNode *node)
34 static void adiumPurpleBlistShow(PurpleBuddyList *list)
39 static void adiumPurpleBlistUpdate(PurpleBuddyList *list, PurpleBlistNode *node)
41 if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
42 PurpleBuddy *buddy = (PurpleBuddy*)node;
44 //Take no action if the relevant account isn't online.
45 if (!purple_buddy_get_account(buddy) || !purple_account_is_connected(purple_buddy_get_account(buddy)))
48 AIListContact *theContact = contactLookupFromBuddy(buddy);
50 PurpleGroup *g = purple_buddy_get_group(buddy);
51 NSString *groupName = ((g && purple_group_get_name(g)) ? [NSString stringWithUTF8String:purple_group_get_name(g)] : nil);
52 NSString *oldGroupName;
53 NSValue *buddyValue = [NSValue valueWithPointer:buddy];
55 //Group changes, including the initial notification of the group
56 //We also use this opportunity to check the contact's name against its formattedUID
57 if (!groupDict) groupDict = [[NSMutableDictionary alloc] init];
59 /* If there is no old group name, or there is and there is no current group name, or the two don't match,
60 * update our group information. */
61 if (!(oldGroupName = [groupDict objectForKey:buddyValue]) ||
63 !([oldGroupName isEqualToString:groupName])) {
65 /* We pass in purple_buddy_get_name(buddy) directly (without filtering or normalizing it) as it may indicate a
66 * formatted version of the UID. We have a signal for when a rename occurs, but passing here lets us get
67 * formatted names which are originally formatted in a way which differs from the results of normalization.
68 * For example, TekJew will normalize to tekjew in AIM; we want to use tekjew internally but display TekJew.
70 NSString *contactName;
71 contactName = [NSString stringWithUTF8String:purple_buddy_get_name(buddy)];
73 //Store the new string in our aliasDict
75 [groupDict setObject:groupName forKey:buddyValue];
77 [groupDict removeObjectForKey:buddyValue];
80 [accountLookup(purple_buddy_get_account(buddy)) updateContact:theContact
82 contactName:contactName];
85 /* We have no way of differentiating when the buddy's alias changes versus when we get an update
86 * for a different status event. We don't want to send to the main thread a used alias every time
87 * we get any update, but we do want to pass on a changed alias. We therefore use the static
88 * aliasDict NSMutableDictionary to track what alias was last used for each buddy. The first invocation,
89 * and subsequent invocations for the same alias, are passed back to the main thread for processing. */
90 const char *alias = purple_buddy_get_alias_only(buddy);
92 NSString *aliasString = [NSString stringWithUTF8String:alias];
93 NSString *oldAliasString;
95 if (!aliasDict) aliasDict = [[NSMutableDictionary alloc] init];
97 if (![aliasString isEqualToString:[theContact UID]] &&
98 (!(oldAliasString = [aliasDict objectForKey:buddyValue]) ||
99 (![oldAliasString isEqualToString:aliasString]))) {
101 //Store the new string in our aliasDict
103 [aliasDict setObject:aliasString forKey:buddyValue];
105 [aliasDict removeObjectForKey:buddyValue];
108 //Send it to the main thread
109 [accountLookup(purple_buddy_get_account(buddy)) updateContact:theContact
110 toAlias:aliasString];
116 //A buddy was removed from the list
117 static void adiumPurpleBlistRemove(PurpleBuddyList *list, PurpleBlistNode *node)
119 NSCAssert(node != nil, @"BlistRemove on null node");
120 if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
121 PurpleBuddy *buddy = (PurpleBuddy*) node;
122 NSValue *buddyValue = [NSValue valueWithPointer:buddy];
124 // AILog(@"adiumPurpleBlistRemove %s",purple_buddy_get_name(buddy));
125 [accountLookup(purple_buddy_get_account(buddy)) removeContact:contactLookupFromBuddy(buddy)];
127 //Clear our dictionaries
128 [groupDict removeObjectForKey:buddyValue];
129 [aliasDict removeObjectForKey:buddyValue];
132 [(id)buddy->node.ui_data release]; buddy->node.ui_data = NULL;
136 static void adiumPurpleBlistDestroy(PurpleBuddyList *list)
138 //Here we're responsible for destroying what we placed in list's ui_data earlier
139 AILog(@"adiumPurpleBlistDestroy");
142 static void adiumPurpleBlistSetVisible(PurpleBuddyList *list, gboolean show)
144 AILog(@"adiumPurpleBlistSetVisible: %i",show);
147 static void adiumPurpleBlistRequestAddBuddy(PurpleAccount *account, const char *username, const char *group, const char *alias)
149 [accountLookup(account) requestAddContactWithUID:[NSString stringWithUTF8String:username]];
152 static void adiumPurpleBlistRequestAddChat(PurpleAccount *account, PurpleGroup *group, const char *alias, const char *name)
154 AILog(@"adiumPurpleBlistRequestAddChat");
157 static void adiumPurpleBlistRequestAddGroup(void)
159 AILog(@"adiumPurpleBlistRequestAddGroup");
162 static PurpleBlistUiOps adiumPurpleBlistOps = {
163 adiumPurpleBlistNewList,
164 adiumPurpleBlistNewNode,
165 adiumPurpleBlistShow,
166 adiumPurpleBlistUpdate,
167 adiumPurpleBlistRemove,
168 adiumPurpleBlistDestroy,
169 adiumPurpleBlistSetVisible,
170 adiumPurpleBlistRequestAddBuddy,
171 adiumPurpleBlistRequestAddChat,
172 adiumPurpleBlistRequestAddGroup
175 PurpleBlistUiOps *adium_purple_blist_get_ui_ops(void)
177 return &adiumPurpleBlistOps;